import 'dart:math';

import 'package:flutter/material.dart';

/// 豆人动画状态效果
// 让豆人的嘴巴开合，也可以让豆人有颜色渐变的动画。可以让它有移动动画、缩放动画、眼睛动一动什么的
class PicMan extends StatefulWidget {
  final Color color;

  const PicMan({super.key, this.color = Colors.blue});

  @override
  State<PicMan> createState() => _PicManState();
}

class _PicManState extends State<PicMan> with SingleTickerProviderStateMixin {
  late AnimationController _animCtrl;
  final ValueNotifier<Color> _color = ValueNotifier(Colors.blue);

  @override
  void initState() {
    super.initState();
    // lowerBound 是运动的下限，upperBound 是运动的上限
    _animCtrl = AnimationController(
        vsync: this,
        duration: const Duration(seconds: 2),
        lowerBound: 10,
        upperBound: 40);
    _animCtrl.addStatusListener(_statusListen);
    _animCtrl.forward();
    //_animCtrl.repeat(reverse: true); // 重复执行动画
  }

  void _statusListen(AnimationStatus status) {
    switch (status) {
      case AnimationStatus.dismissed:
        _color.value = Colors.black;
        break;

      case AnimationStatus.forward:
        _color.value = Colors.blue;
        break;
      case AnimationStatus.reverse:
        _color.value = Colors.red;
        break;

      case AnimationStatus.completed:
        _color.value = Colors.green;
        break;
    }
  }

  @override
  void dispose() {
    _animCtrl.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return CustomPaint(
        size: const Size(100, 100),
        painter: PicManPainter(
            color: _color,
            angle: _animCtrl,
            repaint: Listenable.merge([_animCtrl, _color])));
  }
}

// 在画板中使用合在一起的可监听对象为 repaint 赋值。
class PicManPainter extends CustomPainter {
  final Listenable repaint;
  final ValueNotifier<Color?> color;
  final Animation<double> angle; // 动画角度：与x轴相交的角度

  final Paint _paint = Paint();

  PicManPainter(
      {required this.repaint, required this.color, required this.angle})
      : super(repaint: repaint); // <--- 传入 Listenable 可监听对象

  @override
  void paint(Canvas canvas, Size size) {
    canvas.clipRect(Offset.zero & size); // 裁剪画布
    var halfWidth = size.width / 2;
    var halfHeight = size.height / 2;
    // 画布移到中间
    canvas.translate(halfWidth, halfHeight);
    // 取短的做半径
    final double radius = halfWidth > halfHeight ? halfHeight : halfWidth;

    _drawHead(canvas, radius);
    _drawEye(canvas, radius);
  }

  /// 绘制头
  void _drawHead(Canvas canvas, double radius) {
    var rect = Rect.fromCenter(
        center: const Offset(0, 0), width: radius * 2, height: radius * 2);
    var a = angle.value / 180 * pi;
    var c = color.value ?? Colors.black;
    canvas.drawArc(rect, a, 2 * pi - a.abs() * 2, true, _paint..color = c);
  }

  /// 绘制眼睛
  void _drawEye(Canvas canvas, double radius) {
    canvas.drawCircle(Offset(radius * 0.15, -radius * 0.6), radius * 0.12,
        _paint..color = Colors.white);
  }

  @override
  bool shouldRepaint(covariant PicManPainter oldDelegate) =>
      oldDelegate.repaint != repaint;
}
